﻿using Abp.Authorization;
using Abp.Runtime.Session;
using Abp.UI;
using Paas.App.Interface.Sys.Auth;
using Paas.App.Interface.Sys.Auth.Dtos;
using Paas.App.Interface.Sys.Auth.Messages;
using Paas.Core;
using Paas.Core.Sys.Entities;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Basefr.App;
using Basefr.Auth.Helpers;
using Basefr.Core.Extensions;
using Basefr.Runtime.Helpers;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;

namespace Paas.App.Sys
{
    [Route("Sys-Auth")]
    [AbpAuthorize()]
    public class SysAuthAppService : AppService, ISysAuthAppService
    {
        private readonly IMainRepository<User, long> _userRepo;
        private readonly IMainRepository<UserLogin, long> _userLoginRepo;

        private readonly IConfiguration _configuration;

        public SysAuthAppService(IMainRepository<User, long> userRepo, IMainRepository<UserLogin, long> userLoginRepo, IConfiguration configuration)
        {
            _userRepo = userRepo;
            _userLoginRepo = userLoginRepo;
            _configuration = configuration;
        }

        [HttpPost(nameof(Login))]
        [AbpAllowAnonymous]
        public virtual LoginOutput Login(LoginInput input)
        {
            var user = _userRepo.GetAll()
                .Include(p => p.Organization)
                .Include(p => p.Roles).ThenInclude(p => p.Role.Permissions)
                .FirstOrDefault(p => p.UserName == input.UserName);

            if (user == null || !user.IsActive)
            {
                throw new UserFriendlyException("登录失败，用户不存在或已禁用");
            }

            if (!HashHelper.Validate(input.Password, user.PasswordSalt, user.Password))
            {
                throw new UserFriendlyException("登录失败，密码错误");
            }

            user.LoginTimes++;

            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.Name)
            };

            var token = JwtTokenHelper.CreateBearerToken(claims, _configuration);
            var userDto = ObjectMapper.Map<UserAuthDto>(user);

            userDto.Permissions = user.Roles.SelectMany(r => r.Role.Permissions.Select(p => p.Permission)).Distinct().ToList();

            return new LoginOutput { Token = token, User = userDto };
        }

        [HttpPost(nameof(ChangePassword))]
        public virtual ChangePasswordOutput ChangePassword(ChangePasswordInput input)
        {
            var user = _userRepo.Get(AbpSession.GetUserId());

            if (user == null || !HashHelper.Validate(input.Old, user.PasswordSalt, user.Password))
            {
                throw new UserFriendlyException("原密码错误");
            }

            user.Password = HashHelper.Hash(input.New.Trim(), user.PasswordSalt);

            CurrentUnitOfWork.SaveChanges();

            return new ChangePasswordOutput();
        }

        [HttpPost(nameof(GetCurrentUser))]
        public virtual GetCurrentUserOutput GetCurrentUser(GetCurrentUserInput input)
        {
            var user = _userRepo.GetAll()
                .Include(p => p.Organization)
                .Include(p => p.Roles).ThenInclude(p => p.Role.Permissions)
                .FirstOrDefault(AbpSession.GetUserId());

            var userDto = ObjectMapper.Map<UserAuthDto>(user);

            userDto.Permissions = user.Roles.SelectMany(r => r.Role.Permissions.Select(p => p.Permission)).Distinct().ToList();

            return new GetCurrentUserOutput { User = userDto };
        }
    }
}

